﻿using System;
using System.IO;
using System.Collections.Generic;
using Newtonsoft.Json;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class GameMgr : MonoSingleton<GameMgr>
{
    public float timestep = 0.02f;
    public int steps = 1;
    public Ball ball;
    public bool autoSimulation;

    public Dictionary<string, List<Parameter>> resultMap = new Dictionary<string, List<Parameter>>();

    public Parameter parameter;

    private int _randomSeed = 0;
    public bool playMode = false;

    private void Start()
    {
        Physics2D.autoSimulation = autoSimulation;
        Physics.autoSimulation = autoSimulation;
        ResetAll();
    }

    public void Step()
    {
        for (int i = 0; i < steps; i++)
        {
            Physics2D.Simulate(timestep);
        }
    }

    public void ResetAll()
    {
        ResetParam();
        ball.ResetBall();
    }

    public void ResetParam()
    {
        System.Random random = new System.Random();
        Parameter parameter = new Parameter
        {
            gScale = random.Next(150, 200) / 100f,
            linearDrag = random.Next(0, 10) / 100f,
            bounciness = random.Next(90, 105) / 100f,
            velocity = random.Next(800, 1200) / 100f,
            seed = _randomSeed++,
        };
        this.parameter = parameter;
        UnityEngine.Random.InitState(parameter.seed);
    }

    public void CollectResult(Result result)
    {
        string key = result.targetId;
        if (!this.resultMap.ContainsKey(key))
        {
            this.resultMap[key] = new List<Parameter>();
        }
        this.resultMap[key].Add(this.parameter);
    }


    [ContextMenu("Log")]
    public void Log()
    {
        Debug.Log(new System.Random().Next(0, 2));
    }
}

#if UNITY_EDITOR
[CustomEditor(typeof(GameMgr))]
public class MyCustomEditor : Editor
{
    private string _targetId;
    private bool _isDirty = true;
    private Dictionary<string, List<Parameter>> _resultMap;

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();
        var gameMgr = target as GameMgr;
        if (GUILayout.Button("Step"))
        {
            gameMgr.Step();
        }

        if (GUILayout.Button("SetSimultaionMode"))
        {
            Physics2D.autoSimulation = !Physics2D.autoSimulation;
            Physics.autoSimulation = !Physics.autoSimulation;
        }
        EditorGUILayout.Space(EditorGUIUtility.singleLineHeight);
        _targetId = EditorGUILayout.TextField("target", _targetId);
        if (GUILayout.Button("Save"))
        {
            _isDirty = true;
            var jsonStr = JsonConvert.SerializeObject(gameMgr.resultMap);
            File.WriteAllText(Application.streamingAssetsPath + "/data.json", jsonStr);
        }
        if (GUILayout.Button("Play"))
        {
            gameMgr.playMode = true;
            string key = _targetId;
            if (_isDirty)
            {
                var text = File.ReadAllText(Application.streamingAssetsPath + "/data.json");
                _resultMap = JsonConvert.DeserializeObject<Dictionary<string, List<Parameter>>>(text);
                _isDirty = false;
            }
            if (_resultMap.ContainsKey(key))
            {
                var paramList = _resultMap[key];
                var randIndex = new System.Random().Next(0, paramList.Count);
                gameMgr.parameter = paramList[randIndex];
            }
            else
            {
                Debug.LogWarning("Result does not exist!");
                return;
            }
            UnityEngine.Random.InitState(gameMgr.parameter.seed);
            gameMgr.ball.ResetBall();
        }
        if (GUILayout.Button("ExitPlay"))
        {
            gameMgr.playMode = false;
            gameMgr.ResetAll();
        }

        EditorGUILayout.Space(EditorGUIUtility.singleLineHeight);
        if (GUILayout.Button("Test"))
        {
            var text = File.ReadAllText(Application.streamingAssetsPath + "/data.json");
            var map = JsonConvert.DeserializeObject<Dictionary<string, List<Parameter>>>(text);
        }
    }
}
#endif

public class Parameter
{
    public float gScale;
    public float linearDrag;
    public float bounciness;
    public float velocity;
    public int seed;
}

public class Result
{
    public string targetId;
}